// PR rtl-optimization/104869
// { dg-do run }
// { dg-options "-O2 -fvisibility=hidden -std=c++11" }
// { dg-require-visibility "" }

struct QBasicAtomicInteger {
  [[gnu::noipa]] int loadRelaxed() { return 1; }
};
struct RefCount {
  bool deref() {
    int count = atomic.loadRelaxed();
    if (count)
      return false;
    return deref();
  }
  QBasicAtomicInteger atomic;
};
struct QArrayData {
  RefCount ref;
};
struct QString {
  ~QString();
  QArrayData d;
};
int ok;
QString::~QString() { d.ref.deref(); }
struct Label {
  bool isValid() { return generator; }
  int *generator;
  int index;
};
struct ControlFlow;
struct Codegen {
  [[gnu::noipa]] bool visit();
  ControlFlow *controlFlow;
};
struct ControlFlow {
  enum UnwindType { EE };
  struct UnwindTarget {
    Label linkLabel;
  };
  ControlFlow *parent;
  UnwindType unwindTarget_type;
  UnwindTarget unwindTarget() {
    QString label;
    ControlFlow *flow = this;
    while (flow) {
      Label l = getUnwindTarget(unwindTarget_type, label);
      if (l.isValid())
        return {l};
      flow = flow->parent;
    }
    return UnwindTarget();
  }
  [[gnu::noipa]] Label getUnwindTarget(UnwindType, QString &) {
    Label l = { &ok, 0 };
    return l;
  }
};
[[gnu::noipa]] void foo(int) {
  ok = 1;
}
[[gnu::noipa]] bool Codegen::visit() {
  if (!controlFlow)
    return false;
  ControlFlow::UnwindTarget target = controlFlow->unwindTarget();
  if (target.linkLabel.isValid())
    foo(2);
  return false;
}
#ifdef __hpux__
extern int main(void) __attribute__ ((visibility ("default")));
#endif
int
main() {
  ControlFlow cf = { nullptr, ControlFlow::UnwindType::EE };
  Codegen c = { &cf };
  c.visit();
  if (!ok)
    __builtin_abort ();
}
